#pragma once
#include "base/function.h"
#include "util/noncopyable.h"
#include "base/timeeverymap.h"
#include "base/timeeventset.h"
#include "net/buffer.h"

#include <netinet/in.h>

#include <map>
#include <string>

namespace net_tools
{
  class Eventloop;
  class Tcpclient;
  class Tcpserver;
  namespace base
  {
    class Base_buffer;
    class Channel;
    class Timeevent;
    class Timeevery;
    class Threadpool;
  } // namespace base
  namespace net
  {
    class Buffer_reader;
    class Heartbeat;
    namespace detail
    {
      struct min_heartbeat_struct;
      class heartbeat_struct;
    } // namespace detail
    class Connect : net_tools::util::noncopyable
    {
      friend class Heartbeat;
      friend class Connectpool;
      friend class Buffer;
      friend class net_tools::Tcpclient;
      friend class net_tools::Tcpserver;

    public:
      Connect(Eventloop *eventloop);
      ~Connect();
      // 向日志输出ip及端口
      void Print_ip_port(const char *status);

      // 返回读到的长度 memcpy
      unsigned int Read(void *buf, unsigned int max_size);
      // read only
      Buffer_reader *Read();

      // 写入 返回true写入成功 返回false 连接已被对方close 且已经执行完注册的close回调函数 不能再对网络库进行操作
      bool Write(void *buf, unsigned int len);
      // 返回分包的包头长
      uint32_t Peak();
      // 关闭连接
      void Close();
      // 立即关闭连接 不管还有没有数据没有发送
      void Close_right_now();
      // 添加异步功能
      void Add_task(func task);

      void Send();

      void Append(void *buf, uint32_t len);

      //该connect可读 被关闭
      void Set_read_callback(connect_func cb);
      void Set_close_callback(connect_func cb);
      void Set_lose_heartbeat_callback(connect_func cb);

      net_tools::base::Timeevent *Add_once_time_job_after(func func_, timeval begin_time);
      net_tools::base::Timeevent *Add_once_time_job_at(func func_, timeval begin_time);
      bool Del_once_time_job(net_tools::base::Timeevent *timeevent);
      bool Add_every_time_job(func func_, timeval begin_time, timeval time, int count, const std::string job_name);
      bool Del_every_time_job(const std::string job_name);
      void Add_timejob_after_sec(const std::string job_name, func todo, long int begin_after, long int sec, int count);
      timeval Get_connect_time() { return connect_time_; };

      std::string *Get_Thread_name();
      void *User_data_ptr;

    private:
      // 删除了这个在IO循环中的痕迹 FD也被关闭 缓冲区还没有
      void Clean_connect();
      void Init_channel(net_tools::base::Channel *channel);
      void Set_address(struct sockaddr_in connect_addr);
      //when client close connect,todo
      void Heartbeat_Close_connect_todo();
      void Heartbeat_lose_todo();
      void Rec_heartbeat();
      void Send_heartbeat();

      void Read_callback();
      void Close_callback();
      void Lose_heartbeat_callback();
      void User_want_close_callback();

      static net_tools::base::Threadpool *threadpool_;
      Buffer buffer_;
      net_tools::base::Timeeventset once_time_job_set_;
      net_tools::base::Timeeverymap every_time_job_map_;
      timeval connect_time_;
      timeval last_time_send_message_;
      struct sockaddr_in connect_addr_;
      std::string connect_addr_string_;
      net_tools::base::Channel *channel_;
      net_tools::Eventloop *eventloop_;

      Heartbeat *heartbeat_;
      detail::min_heartbeat_struct *min_heartbeat_struct_;
      detail::heartbeat_struct *heartbeat_struct_;
      uint8_t min_heartbeat_index_;
      bool Is_add_heartbeat_;
      bool Is_send_heartbeat_;

      connect_func read_callback_;
      connect_func close_callback_;
      connect_func lose_heartbeat_callback_;
    };

  } // namespace net
} // namespace net_tools